﻿using mozhi.smarterp.Finance.Banks.Repository;
using mozhi.smarterp.Finance.Basedatas.Events;
using mozhi.smarterp.Finance.Basedatas.Repository;
using Mozhi.Abp.Domain.BasicData.Repositories;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.EventBus.Distributed;

namespace mozhi.smarterp.Finance.Banks
{
    public class BankAccountAppService : FinanceAppService, IBankAccountAppService
    {
        private IDistributedEventBus _distributedEventBus;
        private BankAccountManager _bankAccountManager;
        private IBankAccountRepository _repository;
        private ICurrencyRepository _currencyRepository;
        private IBankTypeRepository _bankTypeRepository;
        public BankAccountAppService(IBankAccountRepository repository ,
            ICurrencyRepository currencyRepository , IBankTypeRepository bankTypeRepository,
            IDistributedEventBus distributedEventBus , BankAccountManager bankAccountManager , IDataAssociationRepository dataAssociationRepository):
            base(dataAssociationRepository)
        {
            _distributedEventBus = distributedEventBus;
            _bankAccountManager = bankAccountManager;
            _repository = repository;
            _bankTypeRepository = bankTypeRepository;
            _currencyRepository = currencyRepository;
        }

        public async Task<List<BankAccountDto>> GetListAsync(BankResultRequestDto filter)
        {
            var bankAccounts = await _repository.GetListAsync(filter.Keyword, null, null);

            var result = ObjectMapper.Map<List<BankAccount>, List<BankAccountDto>>(bankAccounts);

            await LoadOtherInfoAsync(result);

            return result;
        }

        public async Task<BankAccountDto> GetAsync(Guid id)
        {
            var bankAccount = await _repository.GetAsync(id);

            var result = ObjectMapper.Map<BankAccount, BankAccountDto>(bankAccount);

            await LoadOtherInfoAsync(new List<BankAccountDto>() { result });

            return result;
        }

       
        public async Task<BankAccountDto> CreateAsync(BankAccountCreateDto dto)
        {
            var bankAccount = await _bankAccountManager.GetAsync(null, dto.Name, dto.CurrencyId, dto.BankTypeId, dto.Number, dto.EnableReconcile, dto.BranchInfo);

            bankAccount = await _repository.InsertAsync(bankAccount);

            var result = ObjectMapper.Map<BankAccount, BankAccountDto>(bankAccount);

            await LoadOtherInfoAsync(new List<BankAccountDto>() { result });

            return result;
        }


        public async Task<BankAccountDto> UpdateAsync(BankAccountUpdateDto dto)
        {
            var bankAccount = await _bankAccountManager.GetAsync(dto.Id, dto.Name, dto.CurrencyId, dto.BankTypeId, dto.Number, dto.EnableReconcile, dto.BranchInfo);

            bankAccount = await _repository.UpdateAsync(bankAccount);

            var result = ObjectMapper.Map<BankAccount, BankAccountDto>(bankAccount);

            await LoadOtherInfoAsync(new List<BankAccountDto>() { result });

            return result;
        }

        public async Task<bool> DeleteAsync(Guid id)
        {
            var bankAccount = await _repository.GetAsync(id);
            if (bankAccount == null)
                throw new UserFriendlyException("银行账号不存在", "100000");

            await CheckDataAssociation(id);

            await _repository.DeleteAsync(bankAccount);

            if (bankAccount.BankTypeId.HasValue)
                await _distributedEventBus.PublishAsync(new DataAssociationRemoveEvent(bankAccount.Id, bankAccount.BankTypeId.Value));

            await _distributedEventBus.PublishAsync(new DataAssociationRemoveEvent(bankAccount.Id, bankAccount.CurrencyId));

            return true;
        }

        #region
        private async Task LoadOtherInfoAsync(List<BankAccountDto> accounts)
        {
            if (accounts.IsNullOrEmpty())
                return;

            foreach (var account in accounts)
            {
                var currency = await _currencyRepository.GetAsync(account.CurrencyId);

                account.CurrencyName = currency?.Name;

                var bankType = await _bankTypeRepository.GetAsync(account.BankTypeId);

                account.BankTypeName = bankType?.Name;
            }
        }
        #endregion
    }
}
